module Combat

module Projectiles

class Projectile
  @@missiles=CArray.new
  attr_reader :x, :y, :speed, :range, :angle, :id
  def initialize(x, y, speed, range, angle, image, colmap, pushback=true, damagescript=false)
    @x,@y=x,y
    @startx,@starty=x,y
    @speed=speed
    @range=range
    @angle=angle
    @image=image
    @colmap=colmap
    if @colmap.height > @colmap.width
      @page=@colmap.height+1
    else
      @page=@colmap.width+1
    end
    @id=nil
  end
  def draw
    @x+=Gosu::offset_x(@angle, @speed)
    @y+=Gosu::offset_y(@angle, @speed)
    @image.draw_rot(@x, @y, ZOrder::Character, @angle)
    colmap.each { |x, y|
      if not $window.map.traversable(x,y)
        kill
        break
      end
    }
    $window.characters.each { |char|
      if Gosu::distance(@x,@y,char.x,char.y) <= @page
        colmap.each { |x, y|
          if not $window.map.traversable(x,y)
            char.hit()
            kill
            break
          end
        }
      end
    }
    kill if Gosu::distance(@startx, @starty, @x, @y) > @range
  end
  def kill
    @@missiles[@id] = nil
  end
  def register(projectile)
    @id=@@missiles << self
  end
end

class BeamProjectile < Projectile
  def initialize(x, y, speed, range, angle, image, colmap, pushback=true, damagescript=false)
    super(x, y, speed, range, angle, image, colmap, pushback=true, damagescript=false)
    @drawarray=Array.new(Array.new(2))
    @drawcount=0
  end
  def draw
    super
    @drawcount+=1
    @drawarray.push(Array.new(@x,@y)) if @drawcount % 50 == 0
    @drawcount=0 if @drawcount == 500
    @drawarray.each { |elem|
      @image.draw_rot(elem[0], elem[1], ZOrder::Character, @angle)
    }
  end
end

end #module Projectiles

module Actions

class DieAction < ActionBase
  def initialize(animation, params={})
    @animation=animation
    @started=false
  end
  def animation; return @animation; end
  def linkAnims(file); end
  def restart
    Animation.get(@animation.restart)
  end
  def onFinish(character=nil)
    character.die 
  end
end

class AttackBase < ActionBase
  def initialize(name, animation, damage=1, damagescript=false, pushback=true, params={})
    super(name, animation)
    @damage=damage
    @pushback=pushback
    @damagescript=damagescript
    @attackHit=false
  end
  def restart
    super
    Animation.get(@colmap["CFAction"]).restart
    Animation.get(@colmap["CBAction"]).restart
    Animation.get(@colmap["CLAction"]).restart
    Animation.get(@colmap["CRAction"]).restart
    @attackHit=false
  end
  def hit?(character)
    return false
  end
  def onHit(thischar, charhit)
    
  end
  def do(character=nil)
    if not @attackHit
      charhit=hit?(character)
      onHit(character, charhit) if charhit
      @attackHit=true
    end
  end
  def linkAnims(file)
    @colmap = {}
    @animation = {}
    DataFile.new(file).each(2) { |args|
      if args!=false
        if(args[0].slice(0,1)=="C") 
          @colmap[args[0]]=args[1]
        else
          @animation[args[0]]=args[1]
        end
      end
    }
  end
end

class Melee < AttackBase
  def initialize(name, animation, damage=1, damagescript=false, pushback=true, params={})
    super(name, animation, damage=1, damagescript=false, pushback=true, params)
=begin
    if @colmap.height > @colmap.width
      @page=@colmap.height
    else
      @page=@colmap.width
    end
=end
    #page=0
    @page = 0
    m=nil
    @colmap.each_value { |map|
      m=AnimatedCollisionMap.get(map)
      @page=m.height if m.height>@page
      @page=m.width if m.width>@page
    }
  end
  def hit?(character)
    colmap = AnimatedCollisionMap.get(@colmap["C"+MovementBase::DirectionMap[character.direction]+"Action"])
    hit=false
    $window.characters.each { |char|
      if character.tile.id!=char.tile.id and Gosu::distance(char.x, char.y, character.x, character.y) <= @page
        colmap.draw.each { |x, y| 
          if char.tile.contains?(x+character.x, y+character.y)
            hit=char
            break
          end
        }
      end
    }
    return hit
  end
  def onHit(character, charhit)
    if charhit!=nil
      charhit.push(character.x, character.y)
      charhit.hit(@damage)
    end
    RubyScript.new(@damagescript).run if @damagescript
  end
end

class Ranged < AttackBase
  def initialize(name, animation, damage=1, damagescript=false, pushback=true, params={})
    super(name, animation, damage, damagescript, pushback, params)
    @image = Gosu::Image.new($window, params["missile_image"])
    @speed = params["missile_speed"] 
    @range = params["range"] 
    @missiletype=Projectile.new(0, 0, @speed, @range, 0, @pushback, @image, @colmap, @damagescript)
  end
  def do(character=nil)
    missile=@missiletype
    missile.x=character.x
    missile.y=character.y
    missile.angle=Gosu::angle(character.x, character.y, character.targetx, character.targety)
    missile.register
  end
end

class Beam < AttackBase
  def initialize(name, animation, damage=1, damagescript=false, pushback=true, params={})
    super(name, animation, damage, damagescript, pushback, params)
    @image = params["missile_image"]
    @speed = params["missile_speed"] 
    @range = params["range"] 
    @missiletype=BeamProjectile.new(0, 0, @speed, @range, 0, @pushback, @image, @colmap, @damagescript)
  end
  def do(character=nil)
    missile=@missiletype
    missile.x=character.x
    missile.y=character.y
    missile.angle=Gosu::angle(character.x, character.y, character.targetx, character.targety)
    missile.register
  end
end

class DefenseAction < ActionBase
  def do(character=nil)
    
  end
end

end #module Actions

end #module Combat

include Combat::Actions